/*
    SuperCollider real time audio synthesis system
 Copyright (c) 2002 James McCartney. All rights reserved.
    http://www.audiosynth.com

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

// Nick Collins 20 Feb 2006
// revision of algorithm 22 Nov 2007

// Key tracker using weights of FFT bins.

#include "ML.h"
#include "FFT_UGens.h"

// hard coded FFT size
#define N 4096
#define NOVER2 2048

// CONVERT TO m_frameperiod to cope with different sampling rates?
#define FRAMEPERIOD 0.046439909297052

// weighting parameters

// 4096 FFT at 44100 SR
static float g_weights44100[720] = {
    0.89160997732426,   0.10839002267574,   0.39160997732426,   0.10839002267574,   0.2249433106576,
    0.10839002267574,   0.14160997732426,   0.10839002267574,   0.091609977324263,  0.10839002267574,
    0.05827664399093,   0.10839002267574,   0.58784929938181,   0.41215070061819,   0.087849299381813,
    0.41215070061819,   0.25451596604848,   0.078817367284855,  0.087849299381813,  0.16215070061819,
    0.18784929938181,   0.012150700618187,  0.087849299381812,  0.078817367284855,  0.26602607158423,
    0.73397392841577,   0.26602607158423,   0.23397392841577,   0.26602607158423,   0.067307261749107,
    0.016026071584227,  0.23397392841577,   0.066026071584226,  0.13397392841577,   0.099359404917559,
    0.067307261749107,  0.9250662388251,    0.074933761174898,  0.4250662388251,    0.074933761174898,
    0.25839957215844,   0.074933761174898,  0.1750662388251,    0.074933761174898,  0.1250662388251,
    0.074933761174898,  0.091732905491768,  0.074933761174898,  0.56383187935789,   0.43616812064211,
    0.063831879357891,  0.43616812064211,   0.23049854602456,   0.10283478730877,   0.063831879357891,
    0.18616812064211,   0.16383187935789,   0.03616812064211,   0.063831879357892,  0.10283478730877,
    0.18111740708786,   0.81888259291214,   0.18111740708786,   0.31888259291214,   0.18111740708786,
    0.15221592624547,   0.18111740708786,   0.068882592912141,  0.18111740708786,   0.018882592912141,
    0.014450740421193,  0.15221592624547,   0.77564554804057,   0.22435445195943,   0.27564554804057,
    0.22435445195943,   0.1089788813739,    0.22435445195943,   0.02564554804057,   0.22435445195943,
    0.17564554804057,   0.024354451959429,  0.1089788813739,    0.057687785292764,  0.34606307757871,
    0.65393692242129,   0.34606307757871,   0.15393692242129,   0.012729744245378,  0.32060358908796,
    0.096063077578711,  0.15393692242129,   0.14606307757871,   0.053936922421289,  0.012729744245378,
    0.15393692242129,   0.89093630414068,   0.10906369585932,   0.39093630414068,   0.10906369585932,
    0.22426963747401,   0.10906369585932,   0.14093630414068,   0.10906369585932,   0.090936304140679,
    0.10906369585932,   0.057602970807346,  0.10906369585932,   0.40874628442826,   0.59125371557174,
    0.40874628442826,   0.091253715571737,  0.075412951094929,  0.2579203822384,    0.15874628442826,
    0.091253715571737,  0.0087462844282626, 0.19125371557174,   0.075412951094929,  0.091253715571738,
    0.89788375407457,   0.10211624592543,   0.39788375407457,   0.10211624592543,   0.23121708740791,
    0.10211624592543,   0.14788375407457,   0.10211624592543,   0.097883754074573,  0.10211624592543,
    0.06455042074124,   0.10211624592543,   0.35664375687383,   0.64335624312617,   0.35664375687383,
    0.14335624312617,   0.023310423540502,  0.31002290979283,   0.10664375687383,   0.14335624312617,
    0.15664375687384,   0.043356243126163,  0.023310423540502,  0.14335624312616,   0.78321995464853,
    0.21678004535147,   0.28321995464853,   0.21678004535147,   0.11655328798186,   0.21678004535147,
    0.033219954648526,  0.21678004535147,   0.18321995464853,   0.016780045351474,  0.11655328798186,
    0.050113378684807,  0.17569859876363,   0.82430140123637,   0.17569859876363,   0.32430140123637,
    0.17569859876362,   0.15763473456971,   0.17569859876363,   0.074301401236374,  0.17569859876363,
    0.024301401236373,  0.0090319320969575, 0.15763473456971,   0.53205214316846,   0.46794785683154,
    0.032052143168455,  0.46794785683154,   0.19871880983512,   0.13461452349821,   0.032052143168455,
    0.21794785683154,   0.13205214316846,   0.067947856831543,  0.032052143168454,  0.13461452349821,
    0.8501324776502,    0.1498675223498,    0.3501324776502,    0.1498675223498,    0.18346581098354,
    0.1498675223498,    0.1001324776502,    0.1498675223498,    0.050132477650203,  0.1498675223498,
    0.01679914431687,   0.1498675223498,    0.12766375871578,   0.87233624128422,   0.12766375871578,
    0.37233624128422,   0.12766375871578,   0.20566957461755,   0.12766375871578,   0.12233624128422,
    0.12766375871578,   0.072336241284219,  0.12766375871578,   0.039002907950883,  0.36223481417572,
    0.63776518582428,   0.36223481417572,   0.13776518582428,   0.028901480842386,  0.30443185249095,
    0.11223481417572,   0.13776518582428,   0.16223481417572,   0.037765185824279,  0.028901480842386,
    0.13776518582428,   0.55129109608114,   0.44870890391886,   0.05129109608114,   0.44870890391886,
    0.21795776274781,   0.11537557058553,   0.05129109608114,   0.19870890391886,   0.15129109608114,
    0.048708903918859,  0.051291096081139,  0.11537557058553,   0.69212615515742,   0.30787384484258,
    0.19212615515742,   0.30787384484258,   0.025459488490756,  0.30787384484258,   0.19212615515742,
    0.057873844842579,  0.092126155157422,  0.10787384484258,   0.025459488490756,  0.14120717817591,
    0.78187260828136,   0.21812739171864,   0.28187260828136,   0.21812739171864,   0.11520594161469,
    0.21812739171864,   0.031872608281361,  0.21812739171864,   0.18187260828136,   0.018127391718639,
    0.11520594161469,   0.051460725051972,  0.81749256885653,   0.18250743114347,   0.31749256885653,
    0.18250743114347,   0.15082590218986,   0.18250743114348,   0.067492568856526,  0.18250743114347,
    0.017492568856525,  0.18250743114347,   0.15082590218986,   0.015840764476809,  0.79576750814915,
    0.20423249185085,   0.29576750814915,   0.20423249185085,   0.12910084148248,   0.20423249185085,
    0.045767508149147,  0.20423249185085,   0.19576750814915,   0.0042324918508541, 0.12910084148248,
    0.037565825184186,  0.71328751374767,   0.28671248625233,   0.21328751374767,   0.28671248625233,
    0.046620847081009,  0.28671248625232,   0.21328751374767,   0.036712486252327,  0.11328751374767,
    0.086712486252327,  0.046620847081009,  0.12004581958566,   0.56643990929705,   0.43356009070295,
    0.066439909297053,  0.43356009070295,   0.23310657596372,   0.10022675736961,   0.066439909297053,
    0.18356009070295,   0.16643990929705,   0.033560090702949,  0.066439909297053,  0.10022675736961,
    0.35139719752725,   0.64860280247275,   0.35139719752725,   0.14860280247275,   0.018063864193915,
    0.31526946913942,   0.10139719752725,   0.14860280247275,   0.15139719752725,   0.048602802472746,
    0.018063864193915,  0.14860280247275,   0.06410428633691,   0.93589571366309,   0.06410428633691,
    0.43589571366309,   0.064104286336909,  0.26922904699642,   0.06410428633691,   0.18589571366309,
    0.064104286336914,  0.13589571366309,   0.064104286336909,  0.10256238032976,   0.70026495530041,
    0.29973504469959,   0.20026495530041,   0.29973504469959,   0.03359828863374,   0.29973504469959,
    0.20026495530041,   0.049735044699592,  0.10026495530041,   0.099735044699594,  0.03359828863374,
    0.13306837803293,   0.25532751743156,   0.74467248256844,   0.25532751743156,   0.24467248256844,
    0.25532751743157,   0.078005815901766,  0.0053275174315637, 0.24467248256844,   0.055327517431562,
    0.14467248256844,   0.088660850764901,  0.078005815901766,  0.72446962835144,   0.27553037164856,
    0.22446962835144,   0.27553037164856,   0.057802961684772,  0.27553037164856,   0.22446962835144,
    0.025530371648557,  0.12446962835144,   0.075530371648557,  0.057802961684772,  0.1088637049819,
    0.10258219216228,   0.89741780783772,   0.10258219216228,   0.39741780783772,   0.10258219216228,
    0.23075114117105,   0.10258219216228,   0.14741780783772,   0.10258219216228,   0.097417807837718,
    0.10258219216228,   0.064084474504388,  0.38425231031485,   0.61574768968515,   0.38425231031485,
    0.11574768968515,   0.050918976981516,  0.28241435635182,   0.13425231031485,   0.11574768968515,
    0.18425231031485,   0.015747689685151,  0.050918976981516,  0.11574768968515,   0.56374521656272,
    0.43625478343728,   0.063745216562722,  0.43625478343728,   0.23041188322939,   0.10292145010394,
    0.063745216562722,  0.18625478343728,   0.16374521656272,   0.036254783437278,  0.063745216562722,
    0.10292145010394,   0.63498513771305,   0.36501486228695,   0.13498513771305,   0.36501486228695,
    0.30165180437972,   0.031681528953617,  0.13498513771305,   0.11501486228695,   0.034985137713051,
    0.16501486228695,   0.13498513771305,   0.031681528953617,  0.5915350162983,    0.4084649837017,
    0.091535016298302,  0.4084649837017,    0.25820168296497,   0.075131650368367,  0.091535016298302,
    0.1584649837017,    0.1915350162983,    0.0084649837017025, 0.091535016298299,  0.075131650368367,
    0.42657502749535,   0.57342497250465,   0.42657502749535,   0.073424972504654,  0.093241694162018,
    0.24009163917132,   0.17657502749535,   0.073424972504654,  0.026575027495346,  0.17342497250465,
    0.093241694162018,  0.073424972504649,  0.13287981859411,   0.86712018140589,   0.13287981859411,
    0.36712018140589,   0.13287981859411,   0.20045351473923,   0.13287981859411,   0.11712018140589,
    0.1328798185941,    0.067120181405897,  0.13287981859411,   0.033786848072561,  0.7027943950545,
    0.2972056049455,    0.2027943950545,    0.2972056049455,    0.03612772838783,   0.2972056049455,
    0.2027943950545,    0.047205604945496,  0.10279439505451,   0.097205604945492,  0.03612772838783,
    0.13053893827884,   0.12820857267382,   0.87179142732618,   0.12820857267382,   0.37179142732618,
    0.12820857267382,   0.20512476065952,   0.12820857267382,   0.12179142732618,   0.12820857267383,
    0.071791427326173,  0.12820857267382,   0.038458093992849,  0.40052991060082,   0.59947008939918,
    0.40052991060082,   0.099470089399183,  0.067196577267481,  0.26613675606585,   0.15052991060082,
    0.099470089399183,  0.0005299106008124, 0.19947008939919,   0.067196577267481,  0.099470089399186,
    0.51065503486313,   0.48934496513687,   0.010655034863127,  0.48934496513687,   0.1773217015298,
    0.15601163180353,   0.010655034863127,  0.23934496513687,   0.11065503486312,   0.089344965136877,
    0.010655034863134,  0.15601163180353,   0.44893925670289,   0.55106074329711,   0.44893925670289,
    0.051060743297114,  0.11560592336954,   0.21772740996379,   0.19893925670289,   0.051060743297114,
    0.048939256702886,  0.15106074329711,   0.11560592336954,   0.051060743297124,  0.20516438432456,
    0.79483561567544,   0.20516438432456,   0.29483561567544,   0.20516438432456,   0.12816894900878,
    0.20516438432456,   0.044835615675439,  0.0051643843245643, 0.19483561567544,   0.03849771765789,
    0.12816894900878,   0.7685046206297,    0.2314953793703,    0.2685046206297,    0.2314953793703,
    0.10183795396303,   0.2314953793703,    0.018504620629699,  0.2314953793703,    0.1685046206297,
    0.031495379370301,  0.10183795396303,   0.064828712703635,  0.12749043312544,   0.87250956687456,
    0.12749043312544,   0.37250956687456,   0.12749043312544,   0.20584290020789,   0.12749043312544,
    0.12250956687456,   0.12749043312544,   0.072509566874555,  0.12749043312544,   0.039176233541222,
    0.2699702754261,    0.7300297245739,    0.2699702754261,    0.2300297245739,    0.2699702754261,
    0.063363057907234,  0.019970275426104,  0.2300297245739,    0.069970275426101,  0.1300297245739,
    0.10330360875943,   0.063363057907234,  0.1830700325966,    0.8169299674034,    0.1830700325966,
    0.3169299674034,    0.1830700325966,    0.15026330073673,   0.1830700325966,    0.066929967403397,
    0.18307003259659,   0.016929967403405,  0.016403365929932,  0.15026330073673,   0.85315005499069,
    0.14684994500931,   0.35315005499069,   0.14684994500931,   0.18648338832404,   0.1468499450093,
    0.10315005499069,   0.14684994500931,   0.053150054990692,  0.14684994500931,   0.019816721657368,
    0.1468499450093,    0.26575963718821,   0.73424036281179,   0.26575963718821,   0.23424036281179,
    0.26575963718821,   0.067573696145123,  0.015759637188211,  0.23424036281179,   0.065759637188205,
    0.13424036281179,   0.099092970521544,  0.067573696145123,  0.40558879010901,   0.59441120989099,
    0.40558879010901,   0.094411209890993,  0.07225545677566,   0.26107787655767,   0.15558879010901,
    0.094411209890993,  0.0055887901090159, 0.19441120989098,   0.07225545677566,   0.094411209891007,
    0.25641714534767,   0.74358285465233,   0.25641714534767,   0.24358285465233,   0.25641714534767,
    0.07691618798566,   0.0064171453476689, 0.24358285465233,   0.056417145347666,  0.14358285465233,
    0.089750478681007,  0.07691618798566,   0.80105982120163,   0.19894017879837,   0.30105982120163,
    0.19894017879837,   0.13439315453496,   0.19894017879837,   0.051059821201633,  0.19894017879837,
    0.0010598212016248, 0.19894017879838,   0.13439315453496,   0.032273512131705,  0.021310069726255,
    0.97868993027375,   0.021310069726255,  0.47868993027375,   0.021310069726269,  0.31202326360706,
    0.021310069726255,  0.22868993027375,   0.021310069726246,  0.17868993027375,   0.021310069726269,
    0.1453565969404,    0.89787851340579,   0.10212148659421,   0.39787851340579,   0.10212148659421,
    0.23121184673912,   0.10212148659421,   0.14787851340579,   0.10212148659421,   0.097878513405794,
    0.10212148659421,   0.064545180072457,  0.10212148659421,   0.41032876864912,   0.58967123135088,
    0.41032876864912,   0.089671231350877,  0.07699543531578,   0.25633789801755,   0.16032876864912,
    0.089671231350877,  0.010328768649129,  0.18967123135087,   0.07699543531578,   0.089671231350887,
    0.5370092412594,    0.4629907587406,    0.037009241259398,  0.4629907587406,    0.20367590792606,
    0.12965742540727,   0.037009241259398,  0.2129907587406,    0.1370092412594,    0.062990758740602,
    0.037009241259398,  0.12965742540727,   0.25498086625089,   0.74501913374911,   0.25498086625089,
    0.24501913374911,   0.25498086625089,   0.078352467082444,  0.0049808662508894, 0.24501913374911,
    0.054980866250889,  0.14501913374911,   0.088314199584223,  0.078352467082444,  0.53994055085221,
    0.46005944914779,   0.039940550852208,  0.46005944914779,   0.20660721751887,   0.12672611581447,
    0.039940550852208,  0.21005944914779,   0.1399405508522,    0.060059449147798,  0.039940550852198,
    0.12672611581447,   0.36614006519321,   0.63385993480679,   0.36614006519321,   0.13385993480679,
    0.032806731859864,  0.30052660147347,   0.11614006519321,   0.13385993480679,   0.16614006519319,
    0.03385993480681,   0.032806731859864,  0.1338599348068,    0.70630010998138,   0.29369989001862,
    0.20630010998138,   0.29369989001862,   0.039633443314737,  0.2936998900186,    0.20630010998138,
    0.043699890018615,  0.10630010998138,   0.093699890018615,  0.039633443314737,  0.12703322335193
};
static int g_bins44100[720] = {
    5,   6,   10,  11,  15,  16,  20,  21,  25,  26,  30,  31,  5,   6,   10,  11,  16,  17,  21,  22,  27,  28,  32,
    33,  5,   6,   11,  12,  17,  18,  22,  23,  28,  29,  34,  35,  6,   7,   12,  13,  18,  19,  24,  25,  30,  31,
    36,  37,  6,   7,   12,  13,  19,  20,  25,  26,  32,  33,  38,  39,  6,   7,   13,  14,  20,  21,  27,  28,  34,
    35,  40,  41,  7,   8,   14,  15,  21,  22,  28,  29,  36,  37,  43,  44,  7,   8,   15,  16,  22,  23,  30,  31,
    38,  39,  45,  46,  8,   9,   16,  17,  24,  25,  32,  33,  40,  41,  48,  49,  8,   9,   17,  18,  25,  26,  34,
    35,  42,  43,  51,  52,  9,   10,  18,  19,  27,  28,  36,  37,  45,  46,  54,  55,  9,   10,  19,  20,  28,  29,
    38,  39,  48,  49,  57,  58,  10,  11,  20,  21,  30,  31,  40,  41,  51,  52,  61,  62,  10,  11,  21,  22,  32,
    33,  43,  44,  54,  55,  64,  65,  11,  12,  22,  23,  34,  35,  45,  46,  57,  58,  68,  69,  12,  13,  24,  25,
    36,  37,  48,  49,  60,  61,  72,  73,  12,  13,  25,  26,  38,  39,  51,  52,  64,  65,  77,  78,  13,  14,  27,
    28,  40,  41,  54,  55,  68,  69,  81,  82,  14,  15,  28,  29,  43,  44,  57,  58,  72,  73,  86,  87,  15,  16,
    30,  31,  45,  46,  61,  62,  76,  77,  91,  92,  16,  17,  32,  33,  48,  49,  64,  65,  81,  82,  97,  98,  17,
    18,  34,  35,  51,  52,  68,  69,  85,  86,  103, 104, 18,  19,  36,  37,  54,  55,  72,  73,  91,  92,  109, 110,
    19,  20,  38,  39,  57,  58,  77,  78,  96,  97,  115, 116, 20,  21,  40,  41,  61,  62,  81,  82,  102, 103, 122,
    123, 21,  22,  43,  44,  64,  65,  86,  87,  108, 109, 129, 130, 22,  23,  45,  46,  68,  69,  91,  92,  114, 115,
    137, 138, 24,  25,  48,  49,  72,  73,  97,  98,  121, 122, 145, 146, 25,  26,  51,  52,  77,  78,  102, 103, 128,
    129, 154, 155, 27,  28,  54,  55,  81,  82,  109, 110, 136, 137, 163, 164, 28,  29,  57,  58,  86,  87,  115, 116,
    144, 145, 173, 174, 30,  31,  61,  62,  91,  92,  122, 123, 153, 154, 183, 184, 32,  33,  64,  65,  97,  98,  129,
    130, 162, 163, 194, 195, 34,  35,  68,  69,  103, 104, 137, 138, 171, 172, 206, 207, 36,  37,  72,  73,  109, 110,
    145, 146, 182, 183, 218, 219, 38,  39,  77,  78,  115, 116, 154, 155, 192, 193, 231, 232, 40,  41,  81,  82,  122,
    123, 163, 164, 204, 205, 245, 246, 43,  44,  86,  87,  129, 130, 173, 174, 216, 217, 259, 260, 45,  46,  91,  92,
    137, 138, 183, 184, 229, 230, 275, 276, 48,  49,  97,  98,  145, 146, 194, 195, 242, 243, 291, 292, 51,  52,  102,
    103, 154, 155, 205, 206, 257, 258, 308, 309, 54,  55,  109, 110, 163, 164, 218, 219, 272, 273, 327, 328, 57,  58,
    115, 116, 173, 174, 231, 232, 288, 289, 346, 347, 61,  62,  122, 123, 183, 184, 244, 245, 306, 307, 367, 368, 64,
    65,  129, 130, 194, 195, 259, 260, 324, 325, 389, 390, 68,  69,  137, 138, 206, 207, 274, 275, 343, 344, 412, 413,
    72,  73,  145, 146, 218, 219, 291, 292, 364, 365, 436, 437, 77,  78,  154, 155, 231, 232, 308, 309, 385, 386, 462,
    463, 81,  82,  163, 164, 245, 246, 326, 327, 408, 409, 490, 491, 86,  87,  173, 174, 259, 260, 346, 347, 432, 433,
    519, 520, 91,  92,  183, 184, 275, 276, 366, 367, 458, 459, 550, 551, 97,  98,  194, 195, 291, 292, 388, 389, 485,
    486, 583, 584, 102, 103, 205, 206, 308, 309, 411, 412, 514, 515, 617, 618, 109, 110, 218, 219, 327, 328, 436, 437,
    545, 546, 654, 655, 115, 116, 231, 232, 346, 347, 462, 463, 577, 578, 693, 694, 122, 123, 244, 245, 367, 368, 489,
    490, 612, 613, 734, 735, 129, 130, 259, 260, 389, 390, 518, 519, 648, 649, 778, 779, 137, 138, 274, 275, 412, 413,
    549, 550, 687, 688, 824, 825, 145, 146, 291, 292, 436, 437, 582, 583, 728, 729, 873, 874, 154, 155, 308, 309, 462,
    463, 617, 618, 771, 772, 925, 926
};

// 4096 FFT at 48000 SR
static float g_weights48000[720] = { 0.30666666666667,
                                     0.69333333333333,
                                     0.30666666666667,
                                     0.19333333333333,
                                     0.30666666666667,
                                     0.026666666666667,
                                     0.056666666666667,
                                     0.19333333333333,
                                     0.10666666666667,
                                     0.093333333333333,
                                     0.14,
                                     0.026666666666667,
                                     0.027586543807041,
                                     0.97241345619296,
                                     0.027586543807041,
                                     0.47241345619296,
                                     0.02758654380704,
                                     0.30574678952629,
                                     0.027586543807041,
                                     0.22241345619296,
                                     0.027586543807041,
                                     0.17241345619296,
                                     0.02758654380704,
                                     0.13908012285963,
                                     0.73191145326801,
                                     0.26808854673199,
                                     0.23191145326801,
                                     0.26808854673199,
                                     0.065244786601342,
                                     0.26808854673199,
                                     0.23191145326801,
                                     0.018088546731992,
                                     0.13191145326801,
                                     0.068088546731992,
                                     0.065244786601342,
                                     0.10142188006533,
                                     0.41865460692056,
                                     0.58134539307944,
                                     0.41865460692056,
                                     0.081345393079437,
                                     0.08532127358723,
                                     0.2480120597461,
                                     0.16865460692056,
                                     0.081345393079437,
                                     0.018654606920562,
                                     0.18134539307944,
                                     0.08532127358723,
                                     0.081345393079437,
                                     0.086770539160062,
                                     0.91322946083994,
                                     0.086770539160062,
                                     0.41322946083994,
                                     0.086770539160063,
                                     0.24656279417327,
                                     0.086770539160062,
                                     0.16322946083994,
                                     0.086770539160062,
                                     0.11322946083994,
                                     0.086770539160063,
                                     0.079896127506604,
                                     0.73515161776197,
                                     0.26484838223803,
                                     0.23515161776197,
                                     0.26484838223803,
                                     0.068484951095304,
                                     0.26484838223803,
                                     0.23515161776197,
                                     0.014848382238029,
                                     0.13515161776197,
                                     0.064848382238029,
                                     0.068484951095304,
                                     0.098181715571363,
                                     0.36262434726227,
                                     0.63737565273773,
                                     0.36262434726227,
                                     0.13737565273773,
                                     0.02929101392894,
                                     0.30404231940439,
                                     0.11262434726227,
                                     0.13737565273773,
                                     0.16262434726227,
                                     0.037375652737727,
                                     0.02929101392894,
                                     0.13737565273773,
                                     0.96794545252544,
                                     0.032054547474559,
                                     0.46794545252544,
                                     0.032054547474559,
                                     0.30127878585877,
                                     0.03205454747456,
                                     0.21794545252544,
                                     0.032054547474559,
                                     0.16794545252544,
                                     0.03205454747456,
                                     0.13461211919211,
                                     0.03205454747456,
                                     0.54979772942925,
                                     0.45020227057075,
                                     0.049797729429249,
                                     0.45020227057075,
                                     0.21646439609592,
                                     0.11686893723742,
                                     0.049797729429249,
                                     0.20020227057075,
                                     0.14979772942925,
                                     0.05020227057075,
                                     0.049797729429249,
                                     0.11686893723742,
                                     0.10678564881847,
                                     0.89321435118153,
                                     0.10678564881847,
                                     0.39321435118153,
                                     0.10678564881847,
                                     0.22654768451487,
                                     0.10678564881847,
                                     0.14321435118153,
                                     0.10678564881847,
                                     0.093214351181534,
                                     0.10678564881847,
                                     0.059881017848201,
                                     0.63743069905602,
                                     0.36256930094398,
                                     0.13743069905602,
                                     0.36256930094398,
                                     0.30409736572268,
                                     0.029235967610653,
                                     0.13743069905602,
                                     0.11256930094398,
                                     0.037430699056014,
                                     0.16256930094399,
                                     0.13743069905601,
                                     0.029235967610653,
                                     0.14016645162784,
                                     0.85983354837216,
                                     0.14016645162784,
                                     0.35983354837216,
                                     0.14016645162784,
                                     0.1931668817055,
                                     0.14016645162784,
                                     0.10983354837216,
                                     0.14016645162784,
                                     0.059833548372163,
                                     0.14016645162784,
                                     0.02650021503883,
                                     0.61333333333333,
                                     0.38666666666667,
                                     0.11333333333333,
                                     0.38666666666667,
                                     0.28,
                                     0.053333333333333,
                                     0.11333333333333,
                                     0.13666666666667,
                                     0.013333333333334,
                                     0.18666666666667,
                                     0.11333333333333,
                                     0.053333333333333,
                                     0.055173087614081,
                                     0.94482691238592,
                                     0.055173087614081,
                                     0.44482691238592,
                                     0.055173087614081,
                                     0.27816024571925,
                                     0.055173087614081,
                                     0.19482691238592,
                                     0.055173087614082,
                                     0.14482691238592,
                                     0.055173087614081,
                                     0.11149357905259,
                                     0.46382290653602,
                                     0.53617709346398,
                                     0.46382290653602,
                                     0.036177093463982,
                                     0.13048957320268,
                                     0.20284376013065,
                                     0.21382290653602,
                                     0.036177093463982,
                                     0.063822906536019,
                                     0.13617709346398,
                                     0.13048957320268,
                                     0.036177093463982,
                                     0.83730921384113,
                                     0.16269078615887,
                                     0.33730921384113,
                                     0.16269078615887,
                                     0.17064254717446,
                                     0.16269078615887,
                                     0.087309213841126,
                                     0.16269078615887,
                                     0.037309213841124,
                                     0.16269078615888,
                                     0.0039758805077928,
                                     0.16269078615887,
                                     0.17354107832012,
                                     0.82645892167988,
                                     0.17354107832012,
                                     0.32645892167988,
                                     0.17354107832013,
                                     0.15979225501321,
                                     0.17354107832012,
                                     0.076458921679876,
                                     0.17354107832012,
                                     0.026458921679875,
                                     0.0068744116534584,
                                     0.15979225501321,
                                     0.47030323552394,
                                     0.52969676447606,
                                     0.47030323552394,
                                     0.029696764476057,
                                     0.13696990219061,
                                     0.19636343114272,
                                     0.22030323552394,
                                     0.029696764476057,
                                     0.070303235523944,
                                     0.12969676447606,
                                     0.13696990219061,
                                     0.029696764476057,
                                     0.72524869452455,
                                     0.27475130547545,
                                     0.22524869452455,
                                     0.27475130547545,
                                     0.058582027857881,
                                     0.27475130547545,
                                     0.22524869452455,
                                     0.024751305475453,
                                     0.12524869452455,
                                     0.074751305475453,
                                     0.058582027857881,
                                     0.10808463880879,
                                     0.93589090505088,
                                     0.064109094949119,
                                     0.43589090505088,
                                     0.064109094949119,
                                     0.26922423838421,
                                     0.06410909494912,
                                     0.18589090505088,
                                     0.064109094949119,
                                     0.13589090505088,
                                     0.06410909494912,
                                     0.10255757171755,
                                     0.06410909494912,
                                     0.0995954588585,
                                     0.9004045411415,
                                     0.0995954588585,
                                     0.4004045411415,
                                     0.0995954588585,
                                     0.23373787447483,
                                     0.0995954588585,
                                     0.1504045411415,
                                     0.099595458858502,
                                     0.1004045411415,
                                     0.0995954588585,
                                     0.067071207808167,
                                     0.21357129763693,
                                     0.78642870236307,
                                     0.21357129763693,
                                     0.28642870236307,
                                     0.21357129763693,
                                     0.1197620356964,
                                     0.21357129763693,
                                     0.036428702363068,
                                     0.013571297636932,
                                     0.18642870236307,
                                     0.046904630970265,
                                     0.1197620356964,
                                     0.27486139811203,
                                     0.72513860188797,
                                     0.27486139811203,
                                     0.22513860188797,
                                     0.27486139811203,
                                     0.058471935221306,
                                     0.02486139811203,
                                     0.22513860188797,
                                     0.074861398112029,
                                     0.12513860188797,
                                     0.10819473144536,
                                     0.058471935221306,
                                     0.28033290325568,
                                     0.71966709674432,
                                     0.28033290325568,
                                     0.21966709674432,
                                     0.28033290325568,
                                     0.053000430077657,
                                     0.030332903255676,
                                     0.21966709674432,
                                     0.080332903255675,
                                     0.11966709674433,
                                     0.11366623658901,
                                     0.053000430077657,
                                     0.22666666666667,
                                     0.77333333333333,
                                     0.22666666666667,
                                     0.27333333333333,
                                     0.22666666666667,
                                     0.10666666666667,
                                     0.22666666666667,
                                     0.023333333333333,
                                     0.026666666666668,
                                     0.17333333333333,
                                     0.06,
                                     0.10666666666667,
                                     0.11034617522816,
                                     0.88965382477184,
                                     0.11034617522816,
                                     0.38965382477184,
                                     0.11034617522816,
                                     0.22298715810517,
                                     0.11034617522816,
                                     0.13965382477184,
                                     0.11034617522816,
                                     0.089653824771835,
                                     0.11034617522816,
                                     0.056320491438505,
                                     0.92764581307204,
                                     0.072354186927964,
                                     0.42764581307204,
                                     0.072354186927964,
                                     0.26097914640537,
                                     0.072354186927965,
                                     0.17764581307204,
                                     0.072354186927964,
                                     0.12764581307204,
                                     0.072354186927961,
                                     0.094312479738702,
                                     0.072354186927965,
                                     0.67461842768225,
                                     0.32538157231775,
                                     0.17461842768225,
                                     0.32538157231775,
                                     0.0079517610155856,
                                     0.32538157231775,
                                     0.17461842768225,
                                     0.075381572317749,
                                     0.074618427682248,
                                     0.12538157231775,
                                     0.0079517610155856,
                                     0.15871490565108,
                                     0.34708215664025,
                                     0.65291784335975,
                                     0.34708215664025,
                                     0.15291784335975,
                                     0.013748823306917,
                                     0.31958451002642,
                                     0.097082156640248,
                                     0.15291784335975,
                                     0.14708215664025,
                                     0.052917843359751,
                                     0.013748823306917,
                                     0.15291784335975,
                                     0.94060647104789,
                                     0.059393528952114,
                                     0.44060647104789,
                                     0.059393528952114,
                                     0.27393980438122,
                                     0.059393528952114,
                                     0.19060647104789,
                                     0.059393528952114,
                                     0.14060647104789,
                                     0.059393528952111,
                                     0.10727313771455,
                                     0.059393528952114,
                                     0.45049738904909,
                                     0.54950261095091,
                                     0.45049738904909,
                                     0.049502610950906,
                                     0.11716405571576,
                                     0.21616927761757,
                                     0.20049738904909,
                                     0.049502610950906,
                                     0.050497389049093,
                                     0.14950261095091,
                                     0.11716405571576,
                                     0.049502610950905,
                                     0.87178181010177,
                                     0.12821818989823,
                                     0.37178181010177,
                                     0.12821818989823,
                                     0.2051151434351,
                                     0.12821818989823,
                                     0.12178181010177,
                                     0.12821818989823,
                                     0.071781810101766,
                                     0.12821818989823,
                                     0.038448476768437,
                                     0.12821818989823,
                                     0.199190917717,
                                     0.800809082283,
                                     0.199190917717,
                                     0.300809082283,
                                     0.199190917717,
                                     0.13414241561633,
                                     0.199190917717,
                                     0.050809082282999,
                                     0.199190917717,
                                     0.00080908228299563,
                                     0.032524251050333,
                                     0.13414241561633,
                                     0.42714259527386,
                                     0.57285740472614,
                                     0.42714259527386,
                                     0.072857404726136,
                                     0.093809261940531,
                                     0.2395240713928,
                                     0.17714259527386,
                                     0.072857404726136,
                                     0.027142595273864,
                                     0.17285740472614,
                                     0.093809261940531,
                                     0.072857404726136,
                                     0.54972279622406,
                                     0.45027720377594,
                                     0.04972279622406,
                                     0.45027720377594,
                                     0.21638946289073,
                                     0.1169438704426,
                                     0.04972279622406,
                                     0.20027720377594,
                                     0.14972279622406,
                                     0.050277203775937,
                                     0.049722796224065,
                                     0.1169438704426,
                                     0.56066580651135,
                                     0.43933419348865,
                                     0.060665806511352,
                                     0.43933419348865,
                                     0.22733247317802,
                                     0.10600086015531,
                                     0.060665806511352,
                                     0.18933419348865,
                                     0.16066580651135,
                                     0.039334193488651,
                                     0.060665806511352,
                                     0.10600086015531,
                                     0.45333333333333,
                                     0.54666666666667,
                                     0.45333333333333,
                                     0.046666666666667,
                                     0.12,
                                     0.21333333333333,
                                     0.20333333333333,
                                     0.046666666666667,
                                     0.053333333333336,
                                     0.14666666666666,
                                     0.12,
                                     0.046666666666667,
                                     0.22069235045632,
                                     0.77930764954368,
                                     0.22069235045632,
                                     0.27930764954368,
                                     0.22069235045632,
                                     0.11264098287701,
                                     0.22069235045632,
                                     0.029307649543675,
                                     0.020692350456329,
                                     0.17930764954367,
                                     0.054025683789656,
                                     0.11264098287701,
                                     0.85529162614407,
                                     0.14470837385593,
                                     0.35529162614407,
                                     0.14470837385593,
                                     0.1886249594774,
                                     0.14470837385593,
                                     0.10529162614407,
                                     0.14470837385593,
                                     0.055291626144077,
                                     0.14470837385592,
                                     0.021958292810737,
                                     0.14470837385593,
                                     0.3492368553645,
                                     0.6507631446355,
                                     0.3492368553645,
                                     0.1507631446355,
                                     0.015903522031171,
                                     0.31742981130216,
                                     0.099236855364502,
                                     0.1507631446355,
                                     0.1492368553645,
                                     0.050763144635505,
                                     0.015903522031171,
                                     0.1507631446355,
                                     0.6941643132805,
                                     0.3058356867195,
                                     0.1941643132805,
                                     0.3058356867195,
                                     0.027497646613834,
                                     0.3058356867195,
                                     0.1941643132805,
                                     0.055835686719504,
                                     0.094164313280498,
                                     0.1058356867195,
                                     0.027497646613834,
                                     0.13916902005283,
                                     0.88121294209577,
                                     0.11878705790423,
                                     0.38121294209577,
                                     0.11878705790423,
                                     0.21454627542911,
                                     0.11878705790423,
                                     0.13121294209577,
                                     0.11878705790423,
                                     0.081212942095777,
                                     0.11878705790422,
                                     0.047879608762438,
                                     0.11878705790423,
                                     0.90099477809819,
                                     0.099005221901812,
                                     0.40099477809819,
                                     0.099005221901812,
                                     0.23432811143152,
                                     0.09900522190181,
                                     0.15099477809819,
                                     0.099005221901812,
                                     0.10099477809819,
                                     0.099005221901814,
                                     0.067661444764857,
                                     0.09900522190181,
                                     0.74356362020353,
                                     0.25643637979647,
                                     0.24356362020353,
                                     0.25643637979647,
                                     0.076896953536874,
                                     0.25643637979646,
                                     0.24356362020353,
                                     0.0064363797964688,
                                     0.14356362020353,
                                     0.056436379796469,
                                     0.076896953536874,
                                     0.089769713129793,
                                     0.398381835434,
                                     0.601618164566,
                                     0.398381835434,
                                     0.101618164566,
                                     0.065048502100666,
                                     0.26828483123267,
                                     0.148381835434,
                                     0.101618164566,
                                     0.19838183543401,
                                     0.0016181645659913,
                                     0.065048502100666,
                                     0.101618164566,
                                     0.85428519054773,
                                     0.14571480945227,
                                     0.35428519054773,
                                     0.14571480945227,
                                     0.18761852388106,
                                     0.14571480945227,
                                     0.10428519054773,
                                     0.14571480945227,
                                     0.054285190547728,
                                     0.14571480945227,
                                     0.020951857214394,
                                     0.14571480945227,
                                     0.09944559244812,
                                     0.90055440755188,
                                     0.09944559244812,
                                     0.40055440755188,
                                     0.09944559244813,
                                     0.2338877408852,
                                     0.09944559244812,
                                     0.15055440755188,
                                     0.099445592448126,
                                     0.10055440755187,
                                     0.09944559244813,
                                     0.067221074218537,
                                     0.1213316130227,
                                     0.8786683869773,
                                     0.1213316130227,
                                     0.3786683869773,
                                     0.1213316130227,
                                     0.21200172031063,
                                     0.1213316130227,
                                     0.1286683869773,
                                     0.1213316130227,
                                     0.078668386977301,
                                     0.1213316130227,
                                     0.045335053643962,
                                     0.90666666666667,
                                     0.093333333333334,
                                     0.40666666666667,
                                     0.093333333333334,
                                     0.24,
                                     0.093333333333334,
                                     0.15666666666667,
                                     0.093333333333334,
                                     0.10666666666667,
                                     0.093333333333328,
                                     0.073333333333333,
                                     0.093333333333334,
                                     0.44138470091265,
                                     0.55861529908735,
                                     0.44138470091265,
                                     0.05861529908735,
                                     0.10805136757931,
                                     0.22528196575402,
                                     0.19138470091265,
                                     0.05861529908735,
                                     0.041384700912658,
                                     0.15861529908734,
                                     0.10805136757931,
                                     0.058615299087355,
                                     0.71058325228817,
                                     0.28941674771183,
                                     0.21058325228817,
                                     0.28941674771183,
                                     0.043916585621503,
                                     0.28941674771183,
                                     0.21058325228817,
                                     0.039416747711826,
                                     0.11058325228817,
                                     0.089416747711834,
                                     0.043916585621503,
                                     0.12275008104516,
                                     0.698473710729,
                                     0.301526289271,
                                     0.198473710729,
                                     0.301526289271,
                                     0.031807044062343,
                                     0.30152628927099,
                                     0.198473710729,
                                     0.051526289270996,
                                     0.09847371072899,
                                     0.10152628927101,
                                     0.031807044062343,
                                     0.13485962260432,
                                     0.38832862656099,
                                     0.61167137343901,
                                     0.38832862656099,
                                     0.11167137343901,
                                     0.054995293227667,
                                     0.27833804010567,
                                     0.13832862656099,
                                     0.11167137343901,
                                     0.188328626561,
                                     0.011671373439003,
                                     0.054995293227667,
                                     0.111671373439,
                                     0.76242588419157,
                                     0.23757411580843,
                                     0.26242588419157,
                                     0.23757411580843,
                                     0.095759217524896,
                                     0.23757411580844,
                                     0.012425884191572,
                                     0.23757411580843,
                                     0.16242588419157,
                                     0.037574115808434,
                                     0.095759217524896,
                                     0.070907449141771,
                                     0.80198955619638,
                                     0.19801044380362,
                                     0.30198955619638,
                                     0.19801044380362,
                                     0.13532288952971,
                                     0.19801044380362,
                                     0.051989556196375,
                                     0.19801044380362,
                                     0.0019895561963722,
                                     0.19801044380363,
                                     0.13532288952971,
                                     0.031343777136954,
                                     0.48712724040706,
                                     0.51287275959294,
                                     0.48712724040706,
                                     0.012872759592938,
                                     0.15379390707375,
                                     0.17953942625959,
                                     0.23712724040706,
                                     0.012872759592938,
                                     0.087127240407062,
                                     0.11287275959294,
                                     0.15379390707375,
                                     0.012872759592919,
                                     0.796763670868,
                                     0.203236329132,
                                     0.296763670868,
                                     0.203236329132,
                                     0.13009700420133,
                                     0.203236329132,
                                     0.046763670868003,
                                     0.203236329132,
                                     0.19676367086802,
                                     0.0032363291319825,
                                     0.13009700420133,
                                     0.036569662465335,
                                     0.70857038109546,
                                     0.29142961890454,
                                     0.20857038109546,
                                     0.29142961890454,
                                     0.041903714428789,
                                     0.29142961890454,
                                     0.20857038109546,
                                     0.041429618904544,
                                     0.10857038109546,
                                     0.091429618904544,
                                     0.041903714428789,
                                     0.12476295223788,
                                     0.19889118489624,
                                     0.80110881510376,
                                     0.19889118489624,
                                     0.30110881510376,
                                     0.19889118489626,
                                     0.13444214843707,
                                     0.19889118489624,
                                     0.05110881510376,
                                     0.19889118489625,
                                     0.0011088151037484,
                                     0.032224518229593,
                                     0.13444214843707,
                                     0.24266322604541,
                                     0.75733677395459,
                                     0.24266322604541,
                                     0.25733677395459,
                                     0.24266322604541,
                                     0.090670107287925,
                                     0.24266322604541,
                                     0.0073367739545915,
                                     0.042663226045397,
                                     0.1573367739546,
                                     0.075996559378742,
                                     0.090670107287925 };
static int g_bins48000[720] = {
    4,   5,   9,   10,  14,  15,  18,  19,  23,  24,  28,  29,  4,   5,   9,   10,  14,  15,  19,  20,  24,  25,  29,
    30,  5,   6,   10,  11,  15,  16,  21,  22,  26,  27,  31,  32,  5,   6,   11,  12,  16,  17,  22,  23,  27,  28,
    33,  34,  5,   6,   11,  12,  17,  18,  23,  24,  29,  30,  35,  36,  6,   7,   12,  13,  18,  19,  25,  26,  31,
    32,  37,  38,  6,   7,   13,  14,  19,  20,  26,  27,  33,  34,  39,  40,  7,   8,   14,  15,  21,  22,  28,  29,
    35,  36,  42,  43,  7,   8,   14,  15,  22,  23,  29,  30,  37,  38,  44,  45,  7,   8,   15,  16,  23,  24,  31,
    32,  39,  40,  47,  48,  8,   9,   16,  17,  25,  26,  33,  34,  41,  42,  50,  51,  8,   9,   17,  18,  26,  27,
    35,  36,  44,  45,  53,  54,  9,   10,  18,  19,  28,  29,  37,  38,  46,  47,  56,  57,  9,   10,  19,  20,  29,
    30,  39,  40,  49,  50,  59,  60,  10,  11,  21,  22,  31,  32,  42,  43,  52,  53,  63,  64,  11,  12,  22,  23,
    33,  34,  44,  45,  55,  56,  66,  67,  11,  12,  23,  24,  35,  36,  47,  48,  59,  60,  70,  71,  12,  13,  25,
    26,  37,  38,  50,  51,  62,  63,  75,  76,  13,  14,  26,  27,  39,  40,  53,  54,  66,  67,  79,  80,  14,  15,
    28,  29,  42,  43,  56,  57,  70,  71,  84,  85,  14,  15,  29,  30,  44,  45,  59,  60,  74,  75,  89,  90,  15,
    16,  31,  32,  47,  48,  63,  64,  78,  79,  94,  95,  16,  17,  33,  34,  50,  51,  66,  67,  83,  84,  100, 101,
    17,  18,  35,  36,  53,  54,  70,  71,  88,  89,  106, 107, 18,  19,  37,  38,  56,  57,  75,  76,  93,  94,  112,
    113, 19,  20,  39,  40,  59,  60,  79,  80,  99,  100, 119, 120, 21,  22,  42,  43,  63,  64,  84,  85,  105, 106,
    126, 127, 22,  23,  44,  45,  66,  67,  89,  90,  111, 112, 133, 134, 23,  24,  47,  48,  70,  71,  94,  95,  118,
    119, 141, 142, 25,  26,  50,  51,  75,  76,  100, 101, 125, 126, 150, 151, 26,  27,  53,  54,  79,  80,  106, 107,
    132, 133, 159, 160, 28,  29,  56,  57,  84,  85,  112, 113, 140, 141, 168, 169, 29,  30,  59,  60,  89,  90,  119,
    120, 149, 150, 178, 179, 31,  32,  63,  64,  94,  95,  126, 127, 157, 158, 189, 190, 33,  34,  66,  67,  100, 101,
    133, 134, 167, 168, 200, 201, 35,  36,  70,  71,  106, 107, 141, 142, 177, 178, 212, 213, 37,  38,  75,  76,  112,
    113, 150, 151, 187, 188, 225, 226, 39,  40,  79,  80,  119, 120, 159, 160, 198, 199, 238, 239, 42,  43,  84,  85,
    126, 127, 168, 169, 210, 211, 252, 253, 44,  45,  89,  90,  133, 134, 178, 179, 223, 224, 267, 268, 47,  48,  94,
    95,  141, 142, 189, 190, 236, 237, 283, 284, 50,  51,  100, 101, 150, 151, 200, 201, 250, 251, 300, 301, 53,  54,
    106, 107, 159, 160, 212, 213, 265, 266, 318, 319, 56,  57,  112, 113, 168, 169, 225, 226, 281, 282, 337, 338, 59,
    60,  119, 120, 178, 179, 238, 239, 298, 299, 357, 358, 63,  64,  126, 127, 189, 190, 252, 253, 315, 316, 378, 379,
    66,  67,  133, 134, 200, 201, 267, 268, 334, 335, 401, 402, 70,  71,  141, 142, 212, 213, 283, 284, 354, 355, 425,
    426, 75,  76,  150, 151, 225, 226, 300, 301, 375, 376, 450, 451, 79,  80,  159, 160, 238, 239, 318, 319, 397, 398,
    477, 478, 84,  85,  168, 169, 252, 253, 337, 338, 421, 422, 505, 506, 89,  90,  178, 179, 267, 268, 357, 358, 446,
    447, 535, 536, 94,  95,  189, 190, 283, 284, 378, 379, 473, 474, 567, 568, 100, 101, 200, 201, 300, 301, 400, 401,
    501, 502, 601, 602, 106, 107, 212, 213, 318, 319, 424, 425, 530, 531, 637, 638, 112, 113, 225, 226, 337, 338, 450,
    451, 562, 563, 675, 676, 119, 120, 238, 239, 357, 358, 476, 477, 596, 597, 715, 716, 126, 127, 252, 253, 378, 379,
    505, 506, 631, 632, 757, 758, 133, 134, 267, 268, 401, 402, 535, 536, 669, 670, 802, 803, 141, 142, 283, 284, 425,
    426, 567, 568, 708, 709, 850, 851
};

// Krumhansl Kessler profiles (normalised)
// double g_kkminor[12] = { 0.14221523253202, 0.060211188496967, 0.079083352055718, 0.12087171422152, 0.05841383958661,
// 0.079308020669512, 0.057065827903842, 0.10671759155246, 0.089418108290272, 0.060435857110762, 0.075039317007414,
// 0.071219950572905 }; double g_kkmajor[12] = { 0.15195022732711, 0.053362048336923, 0.083273510409189,
// 0.055754965302704, 0.10480976310122, 0.097870303900455, 0.060301507537688, 0.12419239052405, 0.057190715482173,
// 0.087580760947595, 0.054797798516391, 0.068916008614501 };

// following Izmirli; see MIREX2006
static double g_diatonicmajor[12] = { 5.0, 0.0, 3.5, 0.0, 4.5, 4.0, 0.0, 4.5, 0.0, 3.5, 0.0, 4.0 };
static double g_diatonicminor[12] = { 5.0, 0.0, 3.5, 4.5, 0.0, 4.0, 0.0, 4.5, 3.5, 0.0, 0.0, 4.0 };

static int g_minor[7] = { 0, 2, 3, 5, 7, 8, 11 };
static int g_major[7] = { 0, 2, 4, 5, 7, 9, 11 };


// other functions
static void KeyTrack_calculatekey(KeyTrack*, uint32);


void KeyTrack_Ctor(KeyTrack* unit) {
    unit->m_srate = FULLRATE;

    // if sample rate is 88200 or 96000, assume taking double size FFT to start with
    if (unit->m_srate > (44100.0 * 1.5))
        unit->m_srate = unit->m_srate * 0.5;

    if (((int)(unit->m_srate + 0.01)) == 44100) {
        unit->m_weights = g_weights44100;
        unit->m_bins = g_bins44100;
        unit->m_frameperiod = 0.046439909297052;
    } else // else 48000; potentially dangerous if it isn't! Fortunately, shouldn't write any data to unknown memory
    {
        unit->m_weights = g_weights48000;
        unit->m_bins = g_bins48000;
        unit->m_frameperiod = 0.042666666666667;
    }

    // only need space for half!
    unit->m_FFTBuf = (float*)RTAlloc(unit->mWorld, NOVER2 * sizeof(float));
    ClearUnitIfMemFailed(unit->m_FFTBuf);

    // zero chroma
    Clear(12, unit->m_chroma);
    Clear(24, unit->m_key);
    Clear(24, unit->m_histogram);

    // for(j=0;j<60;++j) {
    //		unit->m_leaknote[j]=0.0;
    //	}

    //	for(j=0;j<360;++j) {
    //		unit->m_prevphase[j]=0.0;
    //	}

    // triggers
    // unit->m_triggerid=(int)ZIN0(1);

    unit->m_currentKey = 0;

    // unit->m_frame=0;

    OUT0(0) = 0.f;

    unit->mCalcFunc = (UnitCalcFunc)&KeyTrack_next;
}


void KeyTrack_Dtor(KeyTrack* unit) { RTFree(unit->mWorld, unit->m_FFTBuf); }


void KeyTrack_next(KeyTrack* unit, int wrongNumSamples) {
    // int numSamples = FULLBUFLENGTH;

    // float *output = ZOUT(0);

    float fbufnum = ZIN0(0) + 0.001;

    // next FFT bufffer ready, update
    // assuming at this point that buffer precalculated for any resampling
    if (fbufnum > -0.01f) { // && ( ZIN0(3)<0.5)

        // unit->m_frame= unit->m_frame+1;
        KeyTrack_calculatekey(unit, (uint32)fbufnum);
    }

    // always output current best key
    float outval = unit->m_currentKey;

    // control rate output
    ZOUT0(0) = outval;
}


// calculation function once FFT data ready
void KeyTrack_calculatekey(KeyTrack* unit, uint32 ibufnum) {
    World* world = unit->mWorld;

    SndBuf* buf;

    if (ibufnum >= world->mNumSndBufs) {
        int localBufNum = ibufnum - world->mNumSndBufs;
        Graph* parent = unit->mParent;
        if (localBufNum <= parent->localBufNum) {
            buf = parent->mLocalSndBufs + localBufNum;
        } else {
            buf = world->mSndBufs;
            if (unit->mWorld->mVerbosity > -1) {
                Print("KeyTrack error: Buffer number overrun: %i\n", ibufnum);
            }
        }
    } else {
        buf = world->mSndBufs + ibufnum;
    }

    LOCK_SNDBUF(buf);

    // assumed in this representation
    ToComplexApx(buf);

    const float* data = buf->data;

    // memcpy(unit->m_FFTBuf, data, NOVER2);

    // to hold powers
    float* fftbuf = unit->m_FFTBuf;

    // get powers for bins
    // don't need to calculate past half Nyquist, because no indices involved of harmonics above 10000 Hz or so (see
    // index data at top of file)
    for (int i = 0; i < NOVER2; i += 2) {
        // i>>1 is i/2
        fftbuf[i >> 1] = ((data[i] * data[i]) + (data[i + 1] * data[i + 1]));
    }


    float* chroma = unit->m_chroma;

    float sum;
    int indexbase, index;

    // experimental; added leaky integration on each note; also, only add to sum if harmonic, ie not a transient

    float* weights = unit->m_weights;
    int* bins = unit->m_bins;

    float chromaleak = ZIN0(2);

    // zero for new round (should add leaky integrator here!
    for (int i = 0; i < 12; ++i)
        chroma[i] *= chromaleak;

    for (int i = 0; i < 60; ++i) {
        int chromaindex = (i + 9) % 12; // starts at A1 up to G#6

        sum = 0.0;

        indexbase = 12 * i; // 6 partials, 2 of each

        // transient sum, setting up last values too

        for (int j = 0; j < 12; ++j) { // 12 if 144 data points

            index = indexbase + j;

            // experimental transient detection code, not reliable
            // int binindex= unit->m_bins[index]-1;
            // SCPolar binnow= p->bin[binindex].ToPolarApx();
            // float phaseadvance= (binindex+1)*(TWOPI*0.5); //k * (512/44100) * (44100/1024) //convert bin number to
            // frequency float power= binnow.mag * binnow.mag; //(p->bin[binindex].real)*(p->bin[binindex].real) +
            // (p->bin[binindex].imag)*(p->bin[binindex].imag); //(p->bin[binindex].mag); power *= power;

            // int phaseindex= indexbase+j;
            // float phasenow= binnow.phase; //0.0; //(p->bin[binindex].phase);
            // float prevphase = fmod(unit->m_prevphase[index]+phaseadvance,TWOPI);
            // float a,b,tmp;
            // a=phasenow; b=prevphase;
            // b=phasenow; a=prevphase;

            // if(b<a) {b= b+TWOPI;}

            // float phasechange = sc_min(b-a,a+TWOPI-b); //more complicated, need mod 2pi and to know lower and upper
            // phasesum+= phasechange;
            // unit->m_prevphase[index]= phasenow;

            //((p->bin[index-1].mag) * (p->bin[index-1].mag))

            // printf("comparison %f %f \n",fftbuf[g_bins2[index]], power);
            // sum+= (unit->m_weights[index])* power;

            sum += (weights[index]) * (fftbuf[bins[index]]);
        }


        // transient test here too?
        // if(phasesum>(5*PI)){sum=0.0;}

        // if((i>5) && (i<15))
        // printf("test phasesum %f \n", phasesum);
        // unit->m_leaknote[i] = (0.8*unit->m_leaknote[i]) + sum;

        chroma[chromaindex] += sum; // unit->m_leaknote[i]; //sum;
    }

    float* key = unit->m_key;

    // major
    for (int i = 0; i < 12; ++i) {
        sum = 0.0;
        for (int j = 0; j < 7; ++j) {
            indexbase = g_major[j];

            index = (i + indexbase) % 12;
            // sum+=(chroma[index]*g_kkmajor[indexbase]);

            sum += (chroma[index] * g_diatonicmajor[indexbase]);
        }

        key[i] = sum; // 10*log10(sum+1);
    }

    // minor
    for (int i = 0; i < 12; ++i) {
        sum = 0.0;
        for (int j = 0; j < 7; ++j) {
            indexbase = g_minor[j];

            index = (i + indexbase) % 12;
            // sum+=(chroma[index]*g_kkminor[indexbase]);

            sum += (chroma[index] * g_diatonicminor[indexbase]);
        }

        key[12 + i] = sum;
    }

    float keyleak = ZIN0(1); // fade parameter to 0.01 for histogram in seconds, convert to FFT frames

    // keyleak in seconds, convert to drop time in FFT hop frames (FRAMEPERIOD)
    keyleak = sc_max(0.001f, keyleak / unit->m_frameperiod); // FRAMEPERIOD;

    // now number of frames, actual leak param is decay exponent to reach 0.01 in x seconds, ie 0.01 = leakparam **
    // (x/ffthopsize) 0.01 is -40dB
    keyleak = pow(0.01f, (1.f / keyleak));

    float* histogram = unit->m_histogram;

    int bestkey = 0;
    float bestscore = 0.0;

    for (int i = 0; i < 24; ++i) {
        histogram[i] = (keyleak * histogram[i]) + key[i];

        if (histogram[i] > bestscore) {
            bestscore = histogram[i];
            bestkey = i;
        }

        // printf("%f ",histogram[i]);
    }

    // should find secondbest and only swap if win by a margin

    // printf(" best %d \n\n",bestkey);
    // what is winning currently? find max in histogram
    unit->m_currentKey = bestkey;

    // about 5 times per second
    // if((unit->m_triggerid) && ((unit->m_frame%2==0))) SendTrigger(&unit->mParent->mNode, unit->m_triggerid, bestkey);
}
